
import mathutils
import bpy
from bpy.types import Panel, Menu, Header

import nodeitems_utils
from 全局控制.Node import Nodes
from 全局控制.Node.节点数据类型 import bl_集合数据类型
from 全局控制.Node.节点和插座基类 import bl_NT_Update

from 节点.全局控制.Node.节点和插座基类 import bl_节点基类
from 节点.节点更新 import update节点

from Core.帧动画 import bl_动画数据

import engine.initLIB.load_dll as engineLib
import ctypes
import weakref



from 场景.场景资源管理 import bl_场景管理




import pdb


g_空间数据 = None
g_当前操作节点场景 = None
g_当前激活节点 = None






def f_update_节点树场景(self, context):
	pass



class C_场景节点树(bpy.types.NodeTree):
	bl_label = "Scene Node Tree"
	bl_idname = 'idname_场景对象操作节点树'
	bl_icon = 'MOD_WAVE'
	type = 'FLEX_FLUID'

	m_父节点树 = bpy.props.PointerProperty(name='物体控制节点树', type=bpy.types.NodeTree)
	m_RootNodeName = bpy.props.StringProperty()
	
	m_是否需要更新被动节点 = bpy.props.BoolProperty(name='更新被动节点', default=False)
	m_当前绑定场景 = bpy.props.PointerProperty(name='当前绑定场景', type=bpy.types.Scene, update=f_update_节点树场景)
	
	def __init__(self):
		super(C_场景节点树, self).__init__()
		self.use_fake_user = True
		
		
		
	@classmethod
	def poll(cls, context):
		global g_空间数据
		global g_当前激活节点
		global g_当前操作节点场景
		#print('context.space_data.type = ', context.space_data.type, context.active_node.id_data)
		if context.space_data.type == 'NODE_EDITOR':
			g_当前激活节点 = context.active_node
			if g_当前激活节点 :
				g_当前操作节点场景 = context.active_node.id_data
				
			g_空间数据 = context.space_data
			#初始化
			'''if engineLib.flexCAPI.f_node_是否即时更新节点() :
				#print('update =================')
				pass
			else:
				#print('------ update节点.f_帧改变更新函数绑定 ****************************** ')
				#update节点.f_帧改变更新函数绑定()
				bpy.app.handlers.frame_change_pre.append(update节点.f_帧更新)
				#print('bpy.app.handlers.frame_change_pre = ', bpy.app.handlers.frame_change_pre)
				bpy.app.handlers.load_post.append(update节点.f_初始化更新)
				engineLib.flexCAPI.f_node_初始化更新节点()'''
				#if g_当前操作节点场景 :
				#	g_当前操作节点场景.update()

		return True
		#return context.scene.render.engine == 'CYCLES'
		
	

	def update(self):
		print('=========== 场景更新 ===========')
		if engineLib.flexCAPI.f_node_是否即时更新节点() == False:
			return
		#创建链接 并且 更新节点
		链接变更改节点 = engineLib.flexCAPI.f_取当前插座变更节点(ctypes.c_wchar_p(self.name))
		断开的节点数量 = bl_节点基类.f_断开需要断开的节点输入插座(self.name)
		print('****链接变更改节点**** = ', 链接变更改节点)
		if 链接变更改节点 or 断开的节点数量:
			#更新插座添加改变后的节点
			engineLib.flexCAPI.f_node_计算节点层级(ctypes.c_wchar_p(self.name))
			print('err A')
			if self.m_isUpdate :
				print('err A1 : ', 链接变更改节点)
				self.id_data.f_节点数据更新_更新树(链接变更改节点)
				self.m_上一次链接数量 = len(self.links)
			#print('更新节点 --------------------- 修改连接')
		else :
			print('err A2 : ', 链接变更改节点)
			self.f_重新构建节点()
		engineLib.flexCAPI.f_清除记录当前链接节点(ctypes.c_wchar_p(self.name))




	def f_重新构建节点(self, 完全重构=False):
		global g_当前激活节点

		内部节点数量 = engineLib.flexCAPI.f_node_取要内部节点数量(ctypes.c_wchar_p(self.name))
		print('开始重新构建节点或添加连接 = ', 内部节点数量, len(self.nodes), 完全重构)
		要更新的节点 = []
		#节点数与内部节点数不一致 判断为添加或删除节点更新
		if 完全重构:
		#if 内部节点数量 != len(self.nodes) or 完全重构:
			print('重新构建节点 = ', self.name, self.nodes)
			#单独创建组输入输出节点 = []
			for node in self.nodes:
				#print('node.type = ', node.type)
				if node.type == 'REROUTE':
					bl_节点基类.f_重定向节点_toCPP(self, node)
				elif node.type == 'FRAME':
					pass
				#	单独创建组输入输出节点.append(node)
				else:
					#print('node = ', node)
					node.f_toCPP(tree=self)
					if node.type == 'GROUP':
						tree = node.f_get树()
						#print('重新构建容器节点 = ', tree.name)
						tree.f_重新构建节点(完全重构=True)
			print('f_组输入输出节点_toCPP 单独创建组输入输出节点')
			#for node in 单独创建组输入输出节点:
			#	bl_节点基类.f_组输入输出节点_toCPP(node)
			self.f_重新构建节点链接()
			#bpy.ops.node.translate_attach()
			#bpy.ops.transform.translate()
			#print('更新节点 --------------------- 重构节点')
		#链接减少 判断为链接断开
		elif 内部节点数量 < len(self.nodes) :
			self.f_定点更新([])
		elif self.m_上一次链接数量 > len(self.links):
			self.m_上一次链接数量 = len(self.links)
			
			bl_节点基类.f_断开需要断开的节点输入插座(self.name)
			print('更新节点 --------------------- 断开连接')
		elif len(self.links) > self.m_上一次链接数量 :
			self.m_上一次链接数量 = len(self.links)
			print('err L1', len(self.links), g_当前激活节点)
			if g_当前激活节点 :
				#print('err L2', g_当前激活节点)
				for node in [g_当前激活节点]:
					bl_节点基类.f_构建双向内部链接(node)
					#print('更新节点 --------------------- 双向自动连接', g_当前激活节点, node)
			#nodes = engineLib.flexCAPI.f_get断开输入链接节点(ctypes.c_wchar_p(self.name))
			#for node in nodes:
			#	bl_节点基类.f_构建双向内部链接(node)
			#print('err L3', g_当前激活节点)
		#print('self.name = ', self.name)
		engineLib.flexCAPI.f_node_计算节点层级(ctypes.c_wchar_p(self.name))
		
		self.m_是否需要更新被动节点 = False
		
		#if 完全重构 == False:
		#print(self.name, '---- ----------------- 定点更新')
		





	def f_重新构建节点链接(self):
		for node in self.nodes:
			if node.type == 'FRAME': continue
			#if node.m_是否要更新 :
			engineLib.flexCAPI.f_node_断开所有输出链接(ctypes.c_wchar_p(self.name), ctypes.c_wchar_p(node.name))

		for node in self.nodes:
			if node.type == 'FRAME': continue
			#if node.m_是否要更新 :
			#engineLib.flexCAPI.f_node_断开所有输出链接(ctypes.c_wchar_p(self.name), ctypes.c_wchar_p(node.name))
			if node.type == 'REROUTE':
				bl_节点基类.f_构建内部链接(node)
			else:
				print('node.type = ', node.type, node.name)
				node.f_构建内部链接()


		


	def f_定点更新(self, 要更新节点):
		#内部节点数量 = engineLib.flexCAPI.f_node_取要内部节点数量(ctypes.c_wchar_p(self.name))
		#print('---- f_定点更新---- = 内部节点数量:', 内部节点数量, '  blender节点数量',len(self.nodes))
		要更新节点名称 = []
		print('err I0')
		for node in 要更新节点:
			#print('要更新节点 = ', 要更新节点, node.name)
			要更新节点名称.append(list(node.name))
		print('err I1')
		要退出节点更新 = False
		engineLib.flexCAPI.f_node_绑定更新节点树(ctypes.c_wchar_p(self.name))
		#print('err I2')
		engineLib.flexCAPI.f_node_准备定点更新(ctypes.py_object(要更新节点名称))
		#print('要更新节点名称 = ', 要更新节点名称)
		print('err I3')
		while True:
			print('err I7')
			更新节点组 = engineLib.flexCAPI.f_更新节点树_begin()
			#self.report({'WARNING', 'INFO'}, "Some message!")
			print('err I4 = ', 更新节点组)
			for node in 更新节点组[0]:
				self.nodes[node].f_update()
				#node.f_update()
			#print('err I5 = ', 更新节点组, '更新节点组[1] = ', 更新节点组[1])
			if 更新节点组[1] :
				engineLib.flexCAPI.f_更新节点树_end()
				return
			print('err I6')

	def f_节点数据更新_更新树(self, nodes):
		#print('err J0')
		#if engineLib.flexCAPI.f_node_是否即时更新节点() :
		if self.m_父节点树:
			#print('self.m_父节点树 = ', self.m_父节点树.name, self.m_RootNodeName, nodes)
			上一层根节点 = self.m_父节点树.nodes[self.m_RootNodeName]
			self.m_父节点树.f_节点数据更新_更新树([上一层根节点])
		else:
			print('err J1', self)
			engineLib.flexCAPI.f_取节点层级数量_没有则更新(ctypes.c_wchar_p(self.name))
			print('err J2', nodes)
			self.f_定点更新(nodes)
			#print('err J3')
		
	def f_帧更新(self):
		pass



	def f_节点名称转对象(self, names):
		n = []
		for name in names:
			n.append(self.nodes[name])
		return n

	def f_update(self):
		global g_空间数据
		return bl_NT_Update.f_NT_update(g_空间数据)
		#pass



	











class C_场景对象管理节点树(C_场景节点树):
	bl_label = "引擎场景对象管理节点树"
	bl_idname = 'idname_engine_场景对象管理节点树'
	bl_icon = 'SCENE_DATA'
	#type = 'FLEX_FLUID'

	@classmethod
	def poll(cls, context):
		global g_空间数据
		if context.space_data.type == 'NODE_EDITOR':
			g_空间数据 = context.space_data
		return True

	def __init__(self):
		super(C_场景对象管理节点树, self).__init__()
		self.use_fake_user = True











class C_节点视口_事件处理_进入子树(bpy.types.Operator):
	bl_idname = "node.enter_san_tree"
	bl_label = "进入子树"
	#bl_options = {'REGISTER', 'UNDO'}
	
	def execute(self, context):
		if context.area.ui_type == C_场景节点树.bl_idname :
			node = context.space_data.node_tree.nodes.active
			
			if node and node.bl_static_type == 'GROUP' :
				node.f_进入子集()
				#print('node.node_tree = ', node.node_tree)
				#node.node_tree.m_RootNodeName = node.name
				tree = node.f_get树()
				tree.m_RootNodeName = node.name
				#context.space_data.node_tree = tree
				context.space_data.node_tree = tree
				return {'FINISHED'}
				#print(context.space_data.id_from, context.space_data.node_tree)
		return {'FINISHED'}

class C_节点视口_事件处理_退回父树(bpy.types.Operator):
	bl_idname = "node.enter_back_tree"
	bl_label = "退回父树"
	#bl_options = {'REGISTER', 'UNDO'}
	
	def execute(self, context):
		if context.area.ui_type == C_场景节点树.bl_idname :
			tree = context.space_data.node_tree.m_父节点树
			if tree :
				node = tree.nodes[context.space_data.node_tree.m_RootNodeName]
				node.f_推出子集()
				context.space_data.node_tree = tree
				
			
		return {'FINISHED'}



注册类 = [
	C_场景对象管理节点树,
	C_场景节点树,
	

	C_节点视口_事件处理_进入子树,
	C_节点视口_事件处理_退回父树,
]




def f_draw():
	print('mbt draw')



addon_keymaps = []


def register():
	
	for c in 注册类:
		bpy.utils.register_class(c)
	Nodes.register()


	bpy.types.Scene.m_当前节点树 = bpy.props.PointerProperty(name='物体控制节点树', type=C_场景节点树)
	bpy.types.NodeTree.m_更新节点树组 = bpy.props.BoolProperty(name='更新节点树组')
	bpy.types.NodeTree.m_上一次链接数量 = bpy.props.IntProperty(name='链接线数量', default=-1)

	bpy.types.NodeTree.m_isUpdate = bpy.props.BoolProperty(name='开启更新', default=False)
	
	
	
	wm = bpy.context.window_manager
	km = wm.keyconfigs.addon.keymaps.new(name='树切换', space_type='NODE_EDITOR')#LEFTMOUSE key_modifier='MOUSEMOVE', 
	kmi = km.keymap_items.new(C_节点视口_事件处理_进入子树.bl_idname, type='TAB', value='PRESS') #, ctrl=True, shift=True
	addon_keymaps.append(kmi)
	kmi = km.keymap_items.new(C_节点视口_事件处理_退回父树.bl_idname, type='BACK_SPACE', value='PRESS')
	addon_keymaps.append(kmi)
	print('addon_keymaps = ', addon_keymaps)

	

def unregister():
	for c in 注册类:
		bpy.utils.unregister_class(c)
	Nodes.register()















#bpy.types.SpaceInfo.draw_handler_add(f_draw, (), 'WINDOW', 'POST_PIXEL')
	#wm = bpy.context.window_manager
	#km = wm.keyconfigs.addon.keymaps.new(name='树切换', space_type='NODE_EDITOR')#LEFTMOUSE key_modifier='MOUSEMOVE', 
	#kmi = km.keymap_items.new(C_节点视口_事件处理_进入子树.bl_idname, type='TAB', value='PRESS') #, ctrl=True, shift=True
	#addon_keymaps.append(kmi)
	#kmi = km.keymap_items.new(C_节点视口_事件处理_退回父树.bl_idname, type='BACK_SPACE', value='PRESS')
	#addon_keymaps.append(kmi)
	#print('addon_keymaps = ', addon_keymaps)


